package cn.mybeky.douban.methods {
    
    import cn.mybeky.douban.Douban;
    import cn.mybeky.douban.Movie;
    import cn.mybeky.douban.Tag;
    import cn.mybeky.douban.User;
    import cn.mybeky.douban.events.DoubanResultEvent;
    
    import com.adobe.webapis.flickr.events.*;
    
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.xml.*;
 
    internal class MethodsHelper {
        internal static const ns:Namespace = new Namespace("http://www.w3.org/2005/Atom");
    	internal static const db:Namespace = new Namespace("http://www.douban.com/xmlns/");
    	internal static const gd:Namespace = new Namespace("http://schemas.google.com/g/2005");
    	internal static const API_URL:Object = {"douban.people.getInfo":"people/{userID}", 
    	                                        "douban.people.getUserTags":"people/{userID}/tags",
    	                                        "douban.people.getUserCollection":"people/{userID}/collection",
    	                                        "douban.people.getComments":"people/{userID}/reviews", 
    	                                        "douban.movies.search":"movie/subjects", 
    	                                        "douban.movies.getInfo":"movie/subject/{api_id}"
    	                                           };
        
        internal static function invokeMethod(douban:Douban, 
                                                callBack:Function, 
                                                method:String, 
                                                urlVar:String=null,
                                                queryObj:Object=null):void {
            var url:String = Douban.STATIC_URL + API_URL[method].toString().replace(/{\w+}/, urlVar);
            var query:String = "";
            if (queryObj != null) {
            	query += "?";
	            for (var i:String in queryObj) {
	            	if (queryObj[i] != null) {
	            	    query += i + "=" + encodeURI(queryObj[i]) + "&";    
	            	}
	            }
	            query = query.slice(0, -1);
	        }
	        url += query;
            // Use the "internal" flickrservice namespace to be able to
            // access the urlLoader so we can make the request.
            var loader:URLLoader = douban.urlLoader;
            // Construct a url request with our query string and invoke
            // the Flickr method
            loader.addEventListener("complete", callBack);
            loader.load(new URLRequest(url));
        }
 
        internal static function processAndDispatch(douban:Douban, response:String, result:DoubanResultEvent, propertyName:String = "", parseFunction:Function = null ):void {
            var rsp:Object = processResponse(response, propertyName, parseFunction);
            result.success = rsp.success;
            result.data = rsp.data;
            douban.dispatchEvent(result);
        }

        internal static function processResponse(response:String, propertyName:String, parseFunction:Function ):Object {
            var result:Object = new Object();
            result.data = new Object();
            // Use an XMLDocument to convert a string to XML
            var doc:XMLDocument = new XMLDocument();
            doc.ignoreWhite = true;
            doc.parseXML(response);
            // Get the root rsp node from the document
            var rsp:XMLNode = doc.firstChild;
            
            // Clean up a little
            doc = null; 
            
            result.success = true;
            if ( parseFunction == null ) {
                    // No parse function speficied, just pass through the XML data.
                    // Construct an object that we can access via E4X since
                    // the result we get back from Flickr is an xml response
                    result.data = XML(rsp);
            } else {
                result.data[propertyName] = parseFunction(XML(rsp));
            }    
            
//            if ( rsp.attributes.stat == "ok" ) {
//                result.success = true;
//                
//                // Parse the XML object into a user-defined class (This gives us
//                // nice code hinting, and abstracts away the FlickrAPI a bit - if
//                // the FlickrAPI changes responses we can modify this service
//                // without the user having to update their program code
//                if ( parseFunction == null ) {
//                    // No parse function speficied, just pass through the XML data.
//                    // Construct an object that we can access via E4X since
//                    // the result we get back from Flickr is an xml response
//                    result.data = XML( rsp );
//                } else {
//                    result.data[propertyName] = parseFunction( XML( rsp ) );    
//                }           
//                                
//            } else {
//                result.success = false;
//                
                
//                // In the event that we don't get an xml object
//                // as part of the error returned, just
//                // use the plain text as the error message
//                
//                var error:FlickrError = new FlickrError();
//                if ( rsp.firstChild != null ) 
//                {
//                    error.errorCode = int( rsp.firstChild.attributes.code );
//                    error.errorMessage = rsp.firstChild.attributes.msg;
//                    
//                    result.data.error = error;
//                }
//                else 
//                {
//                    error.errorCode = -1;
//                    error.errorMessage = rsp.nodeValue;
//                    
//                    result.data.error = error;
//                }
                
//            }
            
            
            return result;          
        }
        

        internal static function dateToString( date:Date ):String {
            // Don't do anything if the date is invalid
            if ( date == null ) {
                return "";
            } else {
                return date.getFullYear() + "-" + (date.getMonth() + 1)
                    + "-" + date.getDate() + " " + date.getHours()
                    + ":" + date.getMinutes() + ":" + date.getSeconds();
            }
        }
 
        internal static function stringToDate( str:String = "" ):Date {
            if ( str == "" ) {
                return null;
            }
            
            var date:Date = new Date();
            // split the date into date / time parts
            var parts:Array = str.split( " " );
            
            // See if we have the xxxx-xx-xx xx:xx:xx format
            if ( parts.length == 2 ) {
                var dateParts:Array = parts[0].split( "-" );
                var timeParts:Array = parts[1].split( ":" );
                
                date.setFullYear( dateParts[0] );
                date.setMonth( dateParts[1] - 1 ); // subtract 1 (Jan == 0)
                date.setDate( dateParts[2] );
                date.setHours( timeParts[0] );
                date.setMinutes( timeParts[1] );
                date.setSeconds( timeParts[2] );
            } else {
                // Create a date based on # of seconds since Jan 1, 1970 GMT
                date.setTime( parseInt( str ) * 1000 );
            }
            
            return date;
        }
        

        internal static function parseUser(xml:XML):User {
            var user:User = new User();
            user.id = xml.ns::id.toString();
            user.title = xml.ns::title.toString();
            user.location = xml.ns::location.toString();
            user.content = xml.ns::content.toString();
            for each(var link:XML in xml.ns::link) {
                switch (link.@rel.toString()) {
                	case "self":
                	   user.id = link.@href.toString();                                         
                	   break;
                	case "alternate":
                       user.space = link.@href.toString();
                       break;
                    case "icon":
                       user.avatar = link.@href.toString();
                       break;
                    case "homepage":
                       user.homepage = link.@href.toString();
                       break;
                }
            }
            return user;       
        }
        internal static function parseUserTags(xml:XML):User {
            var user:User = new User();
            for each(var entry:XML in xml.ns::entry) {
            	var tag:Tag = new Tag();
            	tag.id = entry.ns::id.toString();
            	tag.title = entry.ns::title.toString();
            	tag.count = entry.db::count.toString();
            	user.tags.push(tag);
            }
            return user; 	
        }
        internal static function parseUserMovieCollection(xml:XML):User {
        	var user:User = new User();
        	for each(var entry:XML in xml.ns::entry) {
        		var movie:Movie = parseMovie(new XML(entry.db::subject));
        		movie.status = entry.ns::status.toString();
        		movie.updated = entry.ns::updated.toString();
        		movie.userRating.max = entry.gd::rating.@max.toString();
        		movie.userRating.min = entry.gd::rating.@min.toString();
        		movie.userRating.value = entry.gd::rating.@value.toString();
        		for each(var tag:XML in entry.db::tag) {
        			movie.userTags.push(tag.@name.toString());
        		}
        		trace(movie.title, movie.userTags.toString());
        	}
        	return user;
        }
        internal static function parseMovie(xml:XML):Movie {
        	var movie:Movie = new Movie();
        	movie.title = xml.ns::title.toString();
        	movie.summary = xml.ns::summary.toString();
        	for each(var author:XML in xml.ns::author) {
        		movie.director.push(author.ns::name.toString());
        	}
        	for each(var link:XML in xml.ns::link) {
                switch (link.@rel.toString()) {
                    case "self":
                       movie.api_id = link.@href.toString();                                         
                       break;
                    case "alternate":
                       movie.link = link.@href.toString();
                       break;
                    case "image":
                       movie.image = link.@href.toString();
                       break;
                }
            }
            for each(var attribute:XML in xml.db::attribute) {
            	switch (attribute.@name.toString()) {
                    case "country":
                       movie.country.push(attribute.toString());                                         
                       break;
                    case "pubdate":
                       movie.pubdate = attribute.toString();
                       break;
                    case "year":
                       movie.pubdate = attribute.toString();
                       break;
                    case "language":
                       movie.language.push(attribute.toString());
                       break;
                    case "site":
                       movie.website = attribute.toString(); 
                    case "imdb":
                       movie.imdb = attribute.toString();                                         
                       break;
                    case "aka":
                       if (attribute.@lang=="zh_CN") {
                          movie.chinesename = attribute.toString();  
                       } else {
                       	  movie.othername.push(attribute.toString());
                       }
                       break;
                    case "cast":
                       movie.casts.push(attribute.toString());                                         
                       break;
                }
            }
            for each(var tag:XML in xml.db::tag) {
            	var t:Tag = new Tag();
            	t.title = tag.@name.toString();
            	t.count = tag.@count.toString();
            	movie.tags.push(tag);
            }
        	return movie;
        }
        internal static function parseMovieSearchResult(xml:XML):Array {
        	var movies:Array = [];
        	for each(var entry:XML in xml.ns::entry) {
        		var movie:Movie = parseMovie(entry);
        		movies.push(movie);
        	}
        	return movies;
        }
        internal static function parseMovieGetInfoResult(xml:XML):Movie {
        	var movie:Movie = parseMovie(xml);
        	return movie;
        }
    }
    
}